#include "cfg_main.h"

#include <stdio.h>
#include <stdarg.h>

static volatile char TarceEnable = 0x00;
static OS_EVENT *ConsoleSem = NULL;

void putch(char ch)
{
    if (TarceEnable > 0)
    {
#ifdef DEBUG_RS485_4    
        while (Uart3SendNByte((INT8U*)&ch, 1) != TRUE)
#else
		while (Uart1SendNByte((INT8U*)&ch, 1) != TRUE)
#endif
        
        {
            OSTimeDly(OS_TICKS_PER_SEC / 500);
        }
    }
}
char getch(void)
{
    char c = 0;

    if (TarceEnable > 0)
    {
#ifdef DEBUG_RS485_4
        while (Uart3ReceiveNByte((INT8U*)&c, 1) != TRUE)
#else
		while (Uart1ReceiveNByte((INT8U*)&c, 1) != TRUE)
#endif
        {
            OSTimeDly(OS_TICKS_PER_SEC / 500);
        }
    }

    return c;
}

int puts(const char *s)
{
    if (TarceEnable > 0)
    {
        while (*s != 0)
        {
            putch(*s++);
        }
    }

    return 0;
}

static void print_0nx(char ch2, unsigned long l)
{
    if (TarceEnable > 0)
    {
        unsigned char ch;
        int i;

        ch2 = ch2 - '0';
        for (i = ch2 - 1; i >= 0; i--)
        {
            ch = (l >> (i * 4)) & 0x0f;
            if (ch < 10)
            {
                putch(ch + '0');
            }
            else
            {
                putch(ch - 10 + 'A');
            }
        }
    }
}


static void print_d(unsigned long l)
{
    if (TarceEnable > 0)
    {
        unsigned long prod, t;
        unsigned char ch;
        int i, j, flag = 0;

        for (i = 15; i >= 0; i--)
        {
            prod = 1;
            t = l;
            for (j = 0; j < i; j++)
            {
                prod = prod * 10;
                t = t / 10;
            }
            ch = t;
            l -= prod * t;

            if (ch == 0 && flag == 0)
            {
                continue;
            }

            if (ch < 10)
            {
                putch(ch + '0');
            }
            else
            {
                putch('?');
            }

            flag = 1;
        }
    }
}

static void print_x(unsigned long l)
{
    if (TarceEnable > 0)
    {
        unsigned char ch;
        int i, flag = 0;

        for (i = 7; i >= 0; i--)
        {

            ch = (l >> i) & 0x0f;
            if (ch == 0 && flag == 0)
            {
                continue;
            }

            if (ch < 10)
            {
                putch(ch + '0');
            }
            else
            {
                putch(ch - 10 + 'A');
            }

            flag = 1;
        }
    }
}

void ConsoleOnOff(char onOff)
{
    TarceEnable = onOff;
}
char GetConsoleOnOffState(void)
{
    return TarceEnable;
}

void Trace(const char *s, ...)
{
    unsigned char err;

    OS_ENTER_CRITICAL();
    if (ConsoleSem == NULL)
    {
        ConsoleSem = OSSemCreate(1);
    }
    OS_EXIT_CRITICAL();

    OSSemPend(ConsoleSem, 0, &err);

    if (TarceEnable > 0)
    {

        if (1)
        {
            INT8 buff[16];
            INT16U size, i;
            DateTimeType dt;

            RtcGetDateTime(&dt);
            size = sprintf(buff, "%02d-%02d %02d:%02d:%02d:", dt.month, dt.day, dt.hour, dt.minute, dt.second);
            for (i = 0; i < size; i++)
            {
                putch(buff[i]);
            }
        }

        if (1)
        {
            va_list ap;
            unsigned long arg;
            const char *str;
            char ch1, ch2, ch3, lastch = 0;

            va_start(ap, s);

            while (*s != 0)
            {
                if (*s == '%')
                {
                    s++;
                    ch1 = *s++;
                    if (ch1 == 's')
                    {
                        str = (const char*)va_arg(ap, unsigned char *);
                        puts(str);
                    }
                    else if (ch1 == 'd')
                    {
                        arg = va_arg(ap, unsigned long);
                        print_d(arg);
                    }
                    else if (ch1 == 'x')
                    {
                        arg = va_arg(ap, unsigned long);
                        print_x(arg);
                    }
                    else if (ch1 == '\n')
                    {
                        putch(0x0d);
                    }
                    else if (ch1 == '\r')
                    {
                        putch(0x0a);
                    }
                    else if (ch1 == '\0')
                    {
                        break;
                    }
                    else
                    {
                        ch2 = *s++;
                        ch3 = *s++;
                        arg = va_arg(ap, unsigned long);

                        if (ch2 >= '0' && ch2 <= '9' && ch3 != '\0')
                        {
                            print_0nx(ch2, arg);
                        }
                        else
                        {
                            break;
                        }
                    }
                }
                else
                {
                    ch1 = *s++;
                    if (ch1 == '\r')
                    {
                        putch(0x0d);
                    }
                    else if (ch1 == '\n')
                    {
                        if (lastch != '\r')
                        {
                            putch(0x0d);
                        }
                        putch(0x0a);
                    }
                    else if (ch1 == '\0')
                    {
                        break;
                    }
                    else
                    {
                        putch(ch1);
                    }

                    lastch = ch1;
                }
            }
            va_end(ap);
        }
    }

    OSSemPost(ConsoleSem);
}

char BcdTbl[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
void TraceHex(const char *s, unsigned short size)
{
    unsigned char err;
    unsigned short i;

    OS_ENTER_CRITICAL();
    if (ConsoleSem == NULL)
    {
        ConsoleSem = OSSemCreate(1);
    }
    OS_EXIT_CRITICAL();

    OSSemPend(ConsoleSem, 0, &err);

    if (TarceEnable > 0)
    {
        if (1)
        {
            INT8 buff[16];
            INT16U size, i;
            DateTimeType dt;

            RtcGetDateTime(&dt);
            size = sprintf(buff, "%02d-%02d %02d:%02d:%02d:<->", dt.month, dt.day, dt.hour, dt.minute, dt.second);
            for (i = 0; i < size; i++)
            {
                putch(buff[i]);
            }
        }

        for (i = 0; i < size; i++)
        {
            putch(BcdTbl[s[i] >> 4]);
            putch(BcdTbl[s[i] & 0xF]);
            putch(' ');
        }
    }

    putch(0x0d);
    putch(0x0a);

    OSSemPost(ConsoleSem);
}

